#include "testmanager.h"

TestManager::TestManager():
    QObject()
{
    dbFileName = "tests.dt";
    testFileDir = "data/";
    magicNumber = 0xAAFF452C;
}

void TestManager::readTestsDbFromFile()
{
    QFile file;
    quint32 magic;
    quint16 streamVersion;

    file.setFileName(testFileDir + dbFileName);
    if(!file.exists())
    {
        qDebug() << "File " << dbFileName << " no exist.";
        return;
    }
    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "Cannot open file for reading: " << qPrintable(file.errorString());
        return;
    }

    QDataStream in(&file);
    in >> magic >> streamVersion;

    if(magic != magicNumber)
    {
        qDebug() << "File is not recognized by this application";
        return;
    }
    else if(streamVersion > in.version())
    {
        qDebug() << "File is from a more recent version of the" << "application";
        return;
    }

    in >> tests;
}

void TestManager::writeTestsDbToFile()
{
    QFile file(testFileDir + dbFileName);

    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug() << "Cannot open file for writing: " << qPrintable(file.errorString());
        return;
    }

    QDataStream out(&file);
    out << quint32(magicNumber) << quint16(out.version());
    out << tests;
}

void TestManager::setTestFileDir(const QString &fileDirPath)
{
    testFileDir = fileDirPath;
}

void TestManager::addTestFromText(const QString &testTextFile, quint32 testNumVis)
{
    Test ret;
    QFile textFile(testTextFile);
    QString testFileName = "";
    ret.setCountVis(testNumVis);

    if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "in Test::readFromText file \"" << testTextFile << "\" not opening";
        return;
    }

    QTextStream in(&textFile);
    QString test_all = in.readAll();
    textFile.close();

    QStringList test_nodes = test_all.split("I:");
    QStringList tmp1 = test_nodes.at(0).split("\n");
    ret.setName(tmp1.at(0).split(":").at(1).trimmed());

    tmp1.clear();
    for(int i = 1; i < test_nodes.count(); i++)
    {
       readNodeFromText(ret, test_nodes.at(i));
    }

    tests.addTest(ret.getName(), ret.getCountVis());
    testFileName = tests.getTestFileByName(ret.getName());

    QFile testFile(testFileDir + testFileName);
    if (!testFile.open(QIODevice::WriteOnly))
    {
        qDebug() << "in Test::readFromText file \"" << testFileName << "\" not opening";
        return;
    }

    QDataStream out(&testFile);
    out << quint32(magicNumber) << quint16(out.version());
    out << ret;
}

bool TestManager::delTestByName(const QString &testName)
{
    QString fileName = tests.getTestFileByName(testName);
    tests.delTest(testName);
    bool ok = QFile::remove(testFileDir + fileName);
    return ok;
}

QStringList TestManager::getTestList() const
{
    QStringList ret;
    for(uint i = 0; i < tests.count(); i++)
    {
        ret.append(tests.getData().at(i).at(0));
    }
    return ret;
}

Test TestManager::getTestByName(const QString &testName)
{
    Test ret;
    quint32 magic;
    quint16 streamVersion;
    QString testFileName = tests.getTestFileByName(testName);
    QFile file(testFileDir + testFileName);

    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "Cannot open file for reading: " << qPrintable(file.errorString());
        return ret;
    }

    QDataStream in(&file);
    in >> magic >> streamVersion;

    if(magic != magicNumber)
    {
        qDebug() << "File is not recognized by this application";
        return ret;
    }
    else if(streamVersion > in.version())
    {
        qDebug() << "File is from a more recent version of the" << "application";
        return ret;
    }

    in >> ret;
    return ret;
}

Test TestManager::getRunTestByName(const QString &testName)
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

    Test sourceTest, destTest;

    sourceTest = getTestByName(testName);
    quint32 numVis = sourceTest.getCountVis();
    quint32 num = sourceTest.count();
    if(numVis > num)
        numVis = num;
    uint a = 0, b = 0, c = 0, j = 0;
    uint *d = new uint[num];

    for(uint i = 0; i < num; i++)
        d[i] = i;

    while(j < (num * 2))
    {
        a = qrand() % num;
        b = qrand() % num;
        c = d[a];
        d[a] = d[b];
        d[b] = c;
        j++;
    }

    destTest.setName(sourceTest.getName());
    destTest.setCountVis(numVis);

    for(uint i = 0; i < numVis; i++)
    {
        destTest.addNode(sourceTest.getTestNodeById(d[i]));
    }

    delete[] d;
    return destTest;
}

void TestManager::readNodeFromText(Test &test, const QString &text)
{
    TestNode node;
    QStringList str_list = text.split("\n", QString::SkipEmptyParts);

    for(int i = 0; i < str_list.count(); i++)
    {
        if(str_list.at(i).isEmpty())
            continue;
        QStringList tmp = str_list.at(i).split(":");
        if(tmp.count() < 2)
            continue;
        if(tmp.at(0) == "S")
            node.setQuestion(tmp.at(1).trimmed());
        if(tmp.at(0) == "+")
            node.addAnswer(tmp.at(1).trimmed(), 1);
        if(tmp.at(0) == "-")
            node.addAnswer(tmp.at(1).trimmed(), 0);
    }
    test.addNode(node);
}
